use sqlx::PgPool;
use crate::errors::MyError;
use crate::models::teacher::{Teacher,CreateTeacher,UpdateTeacher};


pub async fn get_all_teachers_db(pool: &PgPool) -> Result<Vec<Teacher>, MyError> {
    let rows = sqlx::query_as::<_,Teacher>("select * from teacher").fetch_all(pool).await?;
    match rows.len() {
        0 => Err(MyError::NotFound("Not Found Teachers".into())),
        _ => Ok(rows)
    }
}

pub async fn get_teacher_detail_db(pool: &PgPool, teacher_id: i32) -> Result<Teacher, MyError> {
    let rows = sqlx::query_as::<_,Teacher>("select * from teacher where id = teacher_id")
        .fetch_one(pool)
        .await
        .map_err(|_err| MyError::NotFound("Not Found Teacher In This TeacherId".into()))?;
    Ok(rows)

}

pub async fn post_new_teacher_db(pool: &PgPool, new_teacher: CreateTeacher) -> Result<Teacher, MyError> {
    let rows = sqlx::query_as::<_,Teacher>(r#"insert into teacher (name,picture_url,profile)
    values $1,$2,$3 returning id,name,picture_url,profile"#)
        .bind(new_teacher.name)
        .bind(new_teacher.picture_url)
        .bind(new_teacher.profile)
        .fetch_one(pool)
        .await?;
    Ok(rows)
}

pub async fn update_teacher_details_db(pool: &PgPool, teacher_id: i32, update: UpdateTeacher) -> Result<Teacher, MyError> {
    let rows = sqlx::query_as::<_,Teacher>(r#"select * from teacher where id = $1"#)
    .bind(teacher_id)
        .fetch_one(pool)
        .await
        .map_err(|_err| MyError::NotFound("Teacher is is not found".into()))?;
    let temp = Teacher{
        id: rows.id,
        name: if let Some(name) = update.name{
            name
        }else {
            rows.name
        },
        picture_url: if let Some(price) = update.picture_url{
            price
        }else {
            rows.picture_url
        },
        profile: if let Some(profile) = update.profile{
            profile
        }
        else {
            rows.profile
        }
    };
    let row = sqlx::query_as::<_,Teacher>(r#"
    UPDATE teacher SET name = $1,picture_url = $2,profile = $3 where id = $4
    RETURNING id,name,profile,picture_url"#)
        .bind(temp.name)
        .bind(temp.picture_url)
        .bind(temp.profile)
        .bind(temp.id)
        .fetch_one(pool)
        .await
        .map_err(|_err| MyError::NotFound("Teacher Id not found".into()))?;
    Ok(row)

}
pub async fn delete_teacher_db(pool: &PgPool, teacher_id: i32) -> Result<String, MyError> {
    let rows = sqlx::query!("delete from teacher where id = $1",teacher_id)
        .execute(pool)
        .await
        .map_err(|_err| MyError::DBError("Not Delete Teacher From DB".into()))?;
    Ok(format!("Delete {:?} records", rows))
}
